﻿using KZ.Express.DAL;
using KZ.Express.ENT;
using KZ.Express.Resource;
using KZ.Utilities;
using System.Data;
using System.Linq;

namespace KZ.Express.Task
{
    public class PriceListTask : TaskBase
    {
        private new PriceListENT _entity;
        private ZoneDetailDAL _zoneDAL;
        private OrderDAL _orderDAL;

        public PriceListTask()
            : base()
        {
            _zoneDAL = new ZoneDetailDAL();
            _orderDAL = new OrderDAL();
            base._entity = _entity = new PriceListENT();
            _entitytype = _entity.GetType();
        }

        public DataTable LoadSupplier(int carrierID)
        {
            SearchCriteria search = new SearchCriteria();
            search.Add("CarrierID", carrierID);
            search.Add("IsSupplier", 1);
            DataTable dt = _dalBase.SelectDataTable<SupplierENT>(search);
            DataRow row = dt.NewRow();
            dt.Rows.InsertAt(row, 0);

            return dt;
        }

        public DataTable LoadCarrier()
        {
            DataTable dt = _dalBase.SelectDataTable<CarrierENT>(new SearchCriteria());
            DataRow row = dt.NewRow();
            dt.Rows.InsertAt(row, 0);

            return dt;
        }

        public DataTable LoadZoneDetailType(int zoneID)
        {
            return _zoneDAL.SelectNumberOfType(zoneID);
        }

        public DataTable LoadPartnerPriceList(int priceListID)
        {
            SearchCriteria search = new SearchCriteria();
            search.Add("PriceListID", priceListID);
            return _dalBase.SelectDataTable<PartnerPriceListENT>(search);
        }

        public DataTable LoadPriceListDetail(int priceListID, string type)
        {
            SearchCriteria search = new SearchCriteria();
            search.Add("PriceListID", priceListID);
            search.Add("Type", type);
            DataTable dt = _dalBase.SelectDataTable<PriceListDetailENT>(search);

            return dt;
        }

        /// <summary>
        /// original price
        /// </summary>
        /// <param name="priceList"></param>
        /// <param name="dox"></param>
        /// <param name="wpx"></param>
        /// <returns></returns>
        public int Save(OriginalPriceListENT priceList, DataTable dox, DataTable wpx)
        {
            base._dalBase.BeginTransaction();

            ValidateData(priceList);
            try
            {
                PriceListDetailDAL priceListDetailDAL = new PriceListDetailDAL();
                if (priceList.PriceListID == 0)
                    priceList.PriceListID = base._dalBase.Insert(priceList);
                else
                {
                    base._dalBase.Update(priceList);
                    priceListDetailDAL.Delete(priceList.PriceListID.ToString());
                }

                int colCount = dox.Columns.Count;
                int j = 0;
                foreach (DataRow row in dox.Rows)
                {
                    PriceListDetailENT priceListDetailTemp = new PriceListDetailENT();
                    priceListDetailTemp.PriceListID = priceList.PriceListID;
                    priceListDetailTemp.Type = "DOX";

                    //// convert weight then check weight is exact number or range
                    decimal? weight = Utility.DecimalNParse(row["Weight"]);
                    if (weight.HasValue) //// when weight is exact number, from weight = to weight
                        priceListDetailTemp.FromWeight = priceListDetailTemp.ToWeight = weight;
                    else //// weight is range
                    {
                        string[] temp = Utility.StringParse(row["Weight"]).Split('-');
                        if (temp.Length == 2)
                        {
                            priceListDetailTemp.FromWeight = Utility.DecimalNParse(temp[0]);
                            priceListDetailTemp.ToWeight = Utility.DecimalNParse(temp[1]);
                        }
                    }

                    for (int i = 2; i < colCount; i++)
                    {
                        PriceListDetailENT priceListDetail = new PriceListDetailENT(priceListDetailTemp);
                        priceListDetail.Zone = dox.Columns[i].ColumnName;
                        priceListDetail.ListPrice = Utility.DecimalNParse(row[i]);

                        if (priceListDetail.FromWeight.HasValue && priceListDetail.ListPrice.HasValue)
                        {
                            base._dalBase.Insert(priceListDetail);
                            priceList.PriceListDetails.Add(priceListDetail);
                        }
                    }
                    j++;
                }

                foreach (DataRow row in wpx.Rows)
                {
                    PriceListDetailENT priceListDetailTemp = new PriceListDetailENT();
                    priceListDetailTemp.PriceListID = priceList.PriceListID;
                    priceListDetailTemp.Type = "WPX";

                    //// convert weight then check weight is exact number or range
                    decimal? weight = Utility.DecimalNParse(row["Weight"]);
                    if (weight.HasValue) //// when weight is exact number, from weight = to weight
                        priceListDetailTemp.FromWeight = priceListDetailTemp.ToWeight = weight;
                    else //// weight is range
                    {
                        string[] temp = Utility.StringParse(row["Weight"]).Split('-');
                        if (temp.Length == 2)
                        {
                            priceListDetailTemp.FromWeight = Utility.DecimalNParse(temp[0]);
                            priceListDetailTemp.ToWeight = Utility.DecimalNParse(temp[1]);
                        }
                    }

                    for (int i = 2; i < colCount; i++)
                    {
                        PriceListDetailENT priceListDetail = new PriceListDetailENT(priceListDetailTemp);
                        priceListDetail.Zone = dox.Columns[i].ColumnName;
                        priceListDetail.ListPrice = Utility.DecimalNParse(row[i]);

                        if (priceListDetail.FromWeight.HasValue && priceListDetail.ListPrice.HasValue)
                        {
                            base._dalBase.Insert(priceListDetail);
                            priceList.PriceListDetails.Add(priceListDetail);
                        }
                    }
                    j++;
                }

                UpdateOrderStandardPrice(priceList);

                base._dalBase.CommitTransaction();
                return priceList.PriceListID;
            }
            catch (DataAccessException ex)
            {
                base._dalBase.RollbackTransaction();
                throw new BusinessLogicException(ex.Message);
            }
            catch
            {
                base._dalBase.RollbackTransaction();
                throw new BusinessLogicException(Message.BLM_ERR_SAVE.ToString());
            }
        }

        /// <summary>
        /// customer price
        /// </summary>
        /// <param name="priceList"></param>
        /// <param name="dox"></param>
        /// <param name="wpx"></param>
        /// <param name="customerID"></param>
        /// <returns></returns>
        public int Save(CustomerPriceListENT priceList, DataTable dox, DataTable wpx, string customerID)
        {
            base._dalBase.BeginTransaction();

            ValidateData(priceList);
            try
            {
                PriceListDetailDAL priceListDetailDAL = new PriceListDetailDAL();
                PartnerPriceListDAL partnerPriceListDAL = new PartnerPriceListDAL();

                if (priceList.PriceListID == 0)
                    priceList.PriceListID = base._dalBase.Insert(priceList);
                else
                {
                    base._dalBase.Update(priceList);
                    priceListDetailDAL.Delete(priceList.PriceListID.ToString());
                    partnerPriceListDAL.Delete(priceList.PriceListID.ToString());
                }

                int colCount = dox.Columns.Count;
                foreach (DataRow row in dox.Rows)
                {
                    PriceListDetailENT priceListDetailTemp = new PriceListDetailENT();
                    priceListDetailTemp.PriceListID = priceList.PriceListID;
                    priceListDetailTemp.Type = "DOX";

                    //// convert weight then check weight is exact number or range
                    decimal? weight = Utility.DecimalNParse(row["Weight"]);
                    if (weight.HasValue) //// when weight is exact number, from weight = to weight
                        priceListDetailTemp.FromWeight = priceListDetailTemp.ToWeight = weight;
                    else //// weight is range
                    {
                        string[] temp = Utility.StringParse(row["Weight"]).Split('-');
                        priceListDetailTemp.FromWeight = Utility.DecimalNParse(temp[0]);
                        priceListDetailTemp.ToWeight = Utility.DecimalNParse(temp[1]);
                    }

                    for (int i = 2; i < colCount; i++)
                    {
                        PriceListDetailENT priceListDetail = new PriceListDetailENT(priceListDetailTemp);
                        priceListDetail.Zone = dox.Columns[i].ColumnName;
                        priceListDetail.ListPrice = Utility.DecimalNParse(row[i]);

                        if (priceListDetail.ListPrice.HasValue)
                        {
                            priceListDetail.PriceListDetailID = base._dalBase.Insert(priceListDetail);
                            priceList.PriceListDetails.Add(priceListDetail);
                        }
                    }
                }

                foreach (DataRow row in wpx.Rows)
                {
                    PriceListDetailENT priceListDetailTemp = new PriceListDetailENT();
                    priceListDetailTemp.PriceListID = priceList.PriceListID;
                    priceListDetailTemp.Type = "WPX";

                    //// convert weight then check weight is exact number or range
                    decimal? weight = Utility.DecimalNParse(row["Weight"]);
                    if (weight.HasValue) //// when weight is exact number, from weight = to weight
                        priceListDetailTemp.FromWeight = priceListDetailTemp.ToWeight = weight;
                    else //// weight is range
                    {
                        string[] temp = Utility.StringParse(row["Weight"]).Split('-');
                        priceListDetailTemp.FromWeight = Utility.DecimalNParse(temp[0]);
                        priceListDetailTemp.ToWeight = Utility.DecimalNParse(temp[1]);
                    }

                    for (int i = 2; i < colCount; i++)
                    {

                        PriceListDetailENT priceListDetail = new PriceListDetailENT(priceListDetailTemp);
                        priceListDetail.Zone = dox.Columns[i].ColumnName;
                        priceListDetail.ListPrice = Utility.DecimalNParse(row[i]);

                        if (priceListDetail.ListPrice.HasValue)
                        {
                            priceListDetail.PriceListDetailID = base._dalBase.Insert(priceListDetail);
                            priceList.PriceListDetails.Add(priceListDetail);
                        }
                    }
                }

                partnerPriceListDAL.Insert(priceList.PriceListID, customerID);
                UpdateOrderListPrice(priceList, customerID);

                base._dalBase.CommitTransaction();
                return priceList.PriceListID;
            }
            catch (DataAccessException ex)
            {
                base._dalBase.RollbackTransaction();
                throw new BusinessLogicException(ex.Message);
            }
            catch
            {
                base._dalBase.RollbackTransaction();
                throw new BusinessLogicException(Message.BLM_ERR_SAVE.ToString());
            }
        }

        /// <summary>
        /// update standard price
        /// </summary>
        /// <param name="priceList"></param>
        /// <param name="customerID"></param>
        public void UpdateOrderStandardPrice(OriginalPriceListENT priceList)
        {
            DataTable orders = _orderDAL.SelectForUpdatePrice(priceList.EffectedDate.Value, priceList.ExpiredDate.Value,
                priceList.ZoneID.Value, priceList.CarrierID.Value, priceList.SupplierID.Value, string.Empty);

            foreach (DataRow row in orders.Rows)
            {
                OrderENT order = new OrderENT();
                order.OrderID = Utility.IntParse(row["OrderID"]);
                order.OrderDate = Utility.DateTimeNParse(row["OrderDate"]);
                order.OrderNumber = Utility.StringParse(row["OrderNumber"]);
                order.CarrierID = Utility.IntNParse(row["CarrierID"]);
                order.SupplierID = Utility.IntNParse(row["SupplierID"]);
                order.CustomerID = Utility.IntNParse(row["CustomerID"]);
                order.CountryID = Utility.IntNParse(row["CountryID"]);
                order.Type = Utility.StringParse(row["Type"]);
                order.OriginalPriceListID = Utility.IntNParse(row["OriginalPriceListID"]);
                order.CustomerPriceListID = Utility.IntNParse(row["CustomerPriceListID"]);
                order.Weight = Utility.DecimalNParse(row["Weight"]);
                order.StandardPrice = Utility.DecimalNParse(row["StandardPrice"]);
                order.ListPrice = Utility.DecimalNParse(row["ListPrice"]);
                order.Cost = Utility.DecimalNParse(row["Cost"]);
                order.VNDListOptional = Utility.DecimalNParse(row["VNDListOptional"]);
                order.VAT = Utility.DecimalNParse(row["VAT"]);
                order.Fuel = Utility.DecimalNParse(row["Fuel"]);
                order.Rate = Utility.DecimalNParse(row["Rate"]);
                order.VNDStandardPrice = Utility.DecimalNParse(row["VNDStandardPrice"]);
                order.VNDListPrice = Utility.DecimalNParse(row["VNDListPrice"]);
                order.Description = Utility.StringParse(row["Description"]);
                order.CreatedBy = UserENT.USERID;
                order.UpdatedBy = UserENT.USERID;

                //// update price
                string zone = Utility.StringParse(row["Zone"]);
                int index = priceList.PriceListDetails.FindIndex(p =>
                    p.Zone == zone &&
                    p.Type == order.Type &&
                    p.FromWeight == order.Weight &&
                    p.ToWeight == order.Weight);

                //System.Collections.Generic.List<PriceListDetailENT> temp = new System.Collections.Generic.List<PriceListDetailENT>(priceList.PriceListDetails.Where(p => p.Zone == zone));
                //if (temp != null)
                //    System.Console.WriteLine("123123");
                if (index == -1 & order.Type == "DOX")
                {
                    index = priceList.PriceListDetails.FindIndex(p =>
                        p.Zone == zone &&
                        p.Type == "WPX" &&
                        p.FromWeight <= order.Weight &&
                        p.ToWeight >= order.Weight);
                }

                if (index == -1)
                    order.StandardPrice = null;
                else
                {
                    if (priceList.PriceListDetails[index].FromWeight == priceList.PriceListDetails[index].ToWeight)
                        order.StandardPrice = priceList.PriceListDetails[index].ListPrice;
                    else
                        order.StandardPrice = order.Weight * priceList.PriceListDetails[index].ListPrice;
                }

                order.OriginalPriceListID = priceList.PriceListID;
                order.ComputeVNDStandardPrice();

                _dalBase.Update(order);
            }
        }

        /// <summary>
        /// update list price
        /// </summary>
        /// <param name="priceList"></param>
        /// <param name="customerID"></param>
        public void UpdateOrderListPrice(CustomerPriceListENT priceList, string customerID)
        {
            DataTable orders = _orderDAL.SelectForUpdatePrice(priceList.EffectedDate.Value, priceList.ExpiredDate.Value,
                priceList.ZoneID.Value, priceList.CarrierID.Value, 0, customerID);

            foreach (DataRow row in orders.Rows)
            {
                OrderENT order = new OrderENT();
                order.OrderID = Utility.IntParse(row["OrderID"]);
                order.OrderDate = Utility.DateTimeNParse(row["OrderDate"]);
                order.OrderNumber = Utility.StringParse(row["OrderNumber"]);
                order.CarrierID = Utility.IntNParse(row["CarrierID"]);
                order.SupplierID = Utility.IntNParse(row["SupplierID"]);
                order.CustomerID = Utility.IntNParse(row["CustomerID"]);
                order.CountryID = Utility.IntNParse(row["CountryID"]);
                order.Type = Utility.StringParse(row["Type"]);
                order.OriginalPriceListID = Utility.IntNParse(row["OriginalPriceListID"]);
                order.CustomerPriceListID = Utility.IntNParse(row["CustomerPriceListID"]);
                order.Weight = Utility.DecimalNParse(row["Weight"]);
                order.StandardPrice = Utility.DecimalNParse(row["StandardPrice"]);
                order.ListPrice = Utility.DecimalNParse(row["ListPrice"]);
                order.Cost = Utility.DecimalNParse(row["Cost"]);
                order.VNDListOptional = Utility.DecimalNParse(row["VNDListOptional"]);
                order.VAT = Utility.DecimalNParse(row["VAT"]);
                order.Fuel = Utility.DecimalNParse(row["Fuel"]);
                order.Rate = Utility.DecimalNParse(row["Rate"]);
                order.VNDStandardPrice = Utility.DecimalNParse(row["VNDStandardPrice"]);
                order.VNDListPrice = Utility.DecimalNParse(row["VNDListPrice"]);
                order.Description = Utility.StringParse(row["Description"]);
                order.CreatedBy = UserENT.USERID;
                order.UpdatedBy = UserENT.USERID;

                //// update price
                string zone = Utility.StringParse(row["Zone"]);
                int index = priceList.PriceListDetails.FindIndex(p =>
                    p.Zone == zone &&
                    p.Type == order.Type &&
                    p.FromWeight <= order.Weight &&
                    p.ToWeight >= order.Weight);

                if (index == -1 & order.Type == "DOX")
                {
                    index = priceList.PriceListDetails.FindIndex(p =>
                        p.Zone == zone &&
                        p.Type == "WPX" &&
                        p.FromWeight <= order.Weight &&
                        p.ToWeight >= order.Weight);
                }

                if (index == -1)
                    order.ListPrice = null;
                else
                {
                    if (priceList.PriceListDetails[index].FromWeight == priceList.PriceListDetails[index].ToWeight)
                        order.ListPrice = priceList.PriceListDetails[index].ListPrice;
                    else
                        order.ListPrice = order.Weight * priceList.PriceListDetails[index].ListPrice;
                }

                order.CustomerPriceListID = priceList.PriceListID;
                order.ComputeVNDListPrice();

                _dalBase.Update(order);
            }
        }
    }
}